﻿using Fleck;
using System.Net;

namespace RFIDStation.DeviceDriver.IModules.Impls
{
    public partial class WebSocketModule : IModule
    {
        private readonly ILogger _logger;
        private readonly ViewModel _viewModel;
        private readonly WebSocketServer _server;

        public WebSocketModule( ILoggerFactory loggerFactory, ViewModel viewModel )
        {
            _logger = loggerFactory.CreateLogger( nameof( WebSocketModule ) );
            _viewModel = viewModel;

            FleckLog.LogAction = ( level, message, ex ) =>
            {
                switch ( level )
                {
                    case Fleck.LogLevel.Warn: ConsoleWirter.Warning( $"+ [ws] {message}" ); break;
                    case Fleck.LogLevel.Error: ConsoleWirter.Error( $"+ [ws] {message}" ); break;
                    case Fleck.LogLevel.Debug: break;
                    case Fleck.LogLevel.Info:
                    default: ConsoleWirter.Debug( $"+ [ws]: {message}" ); break;
                }
            };

            _server = new WebSocketServer( _viewModel.AppConfig.TcpServer.WebSocket );
            _server.RestartAfterListenError = true;
        }

        public async Task StartAsync( CancellationToken cancellationToken )
        {
            _server.Start( socket =>
            {
                socket.OnOpen = ( ) =>
                {
                    _logger.Debug( $"ws client connected: {socket.ConnectionInfo.ClientIpAddress}:{socket.ConnectionInfo.ClientPort}, id: {socket.ConnectionInfo.Id}" );

                    //_viewModel.WebSocketClientList.Clear( );
                    _viewModel.WebSocketClientList.Add( socket );
                };

                socket.OnClose = ( ) =>
                {
                    _logger.Debug( $"ws client disconnected: {socket.ConnectionInfo.ClientIpAddress}:{socket.ConnectionInfo.ClientPort}, id: {socket.ConnectionInfo.Id}" );

                    _viewModel.WebSocketClientList.Remove( socket );
                    //_viewModel.UHFReader.StopInventory( );
                };

                socket.OnMessage = data =>
                {
                    _logger.Debug( $"ws 接收客户端消息: {data}" );

                    Dtos.MsgDto msg = null;

                    try
                    {
                        msg = JsonConvert.DeserializeObject<Dtos.MsgDto>( data );
                        if ( msg.Data is null ) msg.Data = new Dictionary<string, object>( );

                        switch ( msg.Cmd.ToLower( ) )
                        {
                            #region ======RFID UHF======
                            case "rfid_uhf_check":
                                {
                                    msg.Data["check"] = _viewModel.RFIDUHFReader.ReaderState != Dev.Integration.UHFReader.Constants.ReaderState.Close;
                                    break;
                                }
                            case "rfid_uhf_scan":
                                {
                                    msg.Data.TryGetValue( "count", out string count );
                                    msg.Data.TryGetValue( "include_tid", out bool includeTID );

                                    var tagList = _viewModel.RFIDUHFInventoryScan( count.ToIntOrDefault( defaultValue: 1 ), includeTID );
                                    msg.Data["count"] = tagList.Count( );
                                    msg.Data["list"] = tagList;
                                    break;
                                }
                            case "rfid_uhf_write":
                                {
                                    msg.Data.GetValueIfNullThrowException( "epc", out string writeEPC );
                                    msg.Data.TryGetValue( "mask", out string maskEPC );
                                    msg.Data.TryGetValue( "audio", out bool audio );

                                    _viewModel.RFIDUHFWriteData( writeEPC, maskEPC, audio );
                                    break;
                                }
                            //case "rfid_uhf_register":
                            //    {
                            //        msg.Data.GetValueIfNullThrowException( "val", out string val ); // 待注册值
                            //        msg.Data.TryGetValue( "audio", out bool audio );

                            //        _viewModel.RFIDUHFRegister( data: val, audio, out var epc );
                            //        msg.Data["epc"] = epc;
                            //        break;
                            //    }
                            //case "rfid_uhf_eas":
                            //    {
                            //        msg.Data.GetValueIfNullThrowException( "epc", out string epc );
                            //        msg.Data.TryGetValue( "enable", out bool enable );

                            //        _viewModel.RFIDUHFEASSet( epc, enable, out var newEPC );
                            //        msg.Data["new_epc"] = newEPC;
                            //        break;
                            //    }
                            #endregion


                            #region ======RFID HF======
                            case "rfid_hf_check":
                                {
                                    msg.Data["check"] = _viewModel.RFIDHFReader.ReaderState != Dev.Integration.HFReader.Constants.ReaderState.Close;
                                    break;
                                }
                            case "rfid_hf_scan":
                                {
                                    msg.Data.TryGetValue( "count", out string count );
                                    msg.Data.TryGetValue( "read_block", out bool readBlock );
                                    msg.Data.TryGetValue( "block_start", out string blockStartIndex );
                                    msg.Data.TryGetValue( "block_count", out string blockCount );

                                    var tagList = _viewModel.RFIDHFInventoryScan( count.ToIntOrDefault( defaultValue: 1 )
                                                                                , readBlock
                                                                                , blockStartIndex.ToIntOrDefault( defaultValue: 0 )
                                                                                , blockCount.ToIntOrDefault( defaultValue: 1 ) );

                                    msg.Data["count"] = tagList.Count;
                                    msg.Data["list"] = tagList;
                                    break;
                                }
                            case "rfid_hf_read":
                                {
                                    msg.Data.TryGetValue( "start", out string start );
                                    msg.Data.TryGetValue( "count", out string count );
                                    msg.Data.TryGetValue( "uid", out string uid );

                                    var dto = _viewModel.RFIDHFReadBlock( uid, start.ToIntOrDefault( defaultValue: 0 ), count.ToIntOrDefault( defaultValue: 1 ) );
                                    msg.Data["uid"] = dto.Key;
                                    msg.Data["block_data"] = dto.Value;
                                    break;
                                }
                            case "rfid_hf_write":
                                {
                                    msg.Data.GetValueIfNullThrowException( "val", out string val ); // 待写入值
                                    msg.Data.TryGetValue( "start", out string start );
                                    msg.Data.TryGetValue( "uid", out string uid );

                                    var dto = _viewModel.RFIDHFWriteBlock( uid, start.ToIntOrDefault( defaultValue: 0 ), data: val );
                                    msg.Data["uid"] = dto.Key;
                                    break;
                                }
                            case "rfid_hf_eas":
                                {
                                    msg.Data.TryGetValue( "eas", out bool enable );
                                    msg.Data.TryGetValue( "uid", out string uid );

                                    var dto = _viewModel.RFIDHFWirteEAS( uid, enable );
                                    msg.Data["uid"] = dto.Key;
                                    break;
                                }
                            case "rfid_hf_afi":
                                {
                                    msg.Data.TryGetValue( "afi", out string afi );
                                    msg.Data.TryGetValue( "uid", out string uid );

                                    var dto = _viewModel.RFIDHFWirteAFI( uid, afi.ToByteOrDefault( 0xC2 ) );    // 0xC2: 外借; 0x07: 在馆; 
                                    msg.Data["uid"] = dto.Key;
                                    break;
                                }
                            #endregion


                            #region ======Card Reader======
                            case "card_reader_check":
                                {
                                    msg.Data["check"] = _viewModel.CardReader.ReaderState == Dev.Integration.HFReader.Constants.ReaderState.Open;
                                    break;
                                }
                            case "card_reader_m1_inventory":
                                {
                                    var tagInfo = _viewModel.CardReader.M1Inventory( );
                                    msg.Data["uid"] = tagInfo.UID;
                                    break;
                                }
                            case "card_reader_m1_read_block":
                                {
                                    msg.Data.TryGetValue( "no", out string no );    // 绝对块号. 范围: 0~63

                                    var blockInfo = _viewModel.CardReader.M1ReadBlock( block: no.ToIntOrDefault( defaultValue: 0 ) );
                                    msg.Data["uid"] = blockInfo.UID;
                                    msg.Data["no"] = blockInfo.BlockNo;
                                    msg.Data["data"] = blockInfo.BlockData;
                                    break;
                                }
                            case "card_reader_m1_write_block":
                                {
                                    msg.Data.TryGetValue( "no", out string no );    // 绝对块号. 范围: 0~63
                                    msg.Data.TryGetValue( "data", out string d );   // 块数据

                                    _viewModel.CardReader.M1WriteBlock( block: no.ToIntOrDefault( defaultValue: 1 ), data: d );
                                    break;
                                }
                            case "card_reader_m1_register":
                                {
                                    msg.Data.GetValueIfNullThrowException( "val", out string val ); // 待注册值
                                    msg.Data.TryGetValue( "audio", out bool audio );

                                    _viewModel.M1Register( data: val, audio, out var uid, out var blockNo, out var blockData );
                                    msg.Data["uid"] = uid;
                                    msg.Data["no"] = blockNo;
                                    msg.Data["data"] = blockData;
                                    break;
                                }
                            #endregion


                            #region ======扫描器======
                            case "scanner_check":
                                {
                                    msg.Data["check"] = _viewModel.Scanner.IsOpened;
                                    break;
                                }
                            case "scanner_scan":
                                {
                                    _viewModel.Scanner.Scan( );
                                    break;
                                }
                            #endregion


                            case "test":
                                {
                                    break;
                                }
                            default: throw new Exception( $"无效的指令: {msg.Cmd}" );
                        }
                    }
                    catch ( Dev.Integration.HFReader.ReaderException ex )
                    {
                        msg.Status = ex.Code;
                        msg.Error = ex.Message;
                    }
                    catch ( KeyNotFoundException ex )
                    {
                        msg.Status = (int)HttpStatusCode.NotFound;
                        msg.Error = ex.Message;
                    }
                    catch ( Exception ex )
                    {
                        msg.Status = (int)HttpStatusCode.BadRequest;
                        msg.Error = ex.Message;
                    }

                    // 响应客户端消息
                    var message = msg.ToJson( );
                    socket.Send( message );
                    _logger.Debug( $"ws 响应客户端消息: {message}" );
                };
            } );


            _logger.Info( $"注册成功. {_server.Location}" );
            await Task.CompletedTask;
        }

        public async Task StopAsync( CancellationToken cancellationToken )
        {
            _server.Dispose( );

            _logger.Info( $"注销成功" );
            await Task.CompletedTask;
        }
    }
}
